package nl.weeaboo.sh.danmaku;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import nl.weeaboo.sh.danmaku.ColGrid.ColRectMode;
import nl.weeaboo.sh.objects.Sprite;

public class Universe implements Iterable<ShotModel> {

	public final int rw, rh;	
	public final int w, h;	
	private ColGrid colGrid;
	private Set<ShotModel> shots;
	private List<ShotModel> addList;
	private List<ShotModel> removeList;
	
	public Universe(int rw, int rh) {
		this.rw = rw;
		this.rh = rh;
		int gridSize = ColGrid.gridSize;

		w = rw/gridSize + 1;
		h = rh/gridSize + 1;		
		colGrid = new ColGrid(w, h, 8);
		
		shots = new HashSet<ShotModel>();
		addList = new LinkedList<ShotModel>();
		removeList = new ArrayList<ShotModel>();
	}
	
	//Functions
	public void addShot(ShotModel s) {
		addList.add(s);
	}
	public void removeShot(ShotModel s) {
		s.kill();
		
		addList.remove(s);
		removeList.add(s);
	}
	
	public void initShots(List<ShotModel> addList) {
		for (ShotModel s : addList) {
			shots.add(s);
			updateShotPosition(s);
		}
		addList.clear();
	}
	public void garbageCollect(List<ShotModel> removeList) {
		for (ShotModel s : removeList) {
			shots.remove(s);
			colGrid.remove(s);
		}		
		removeList.clear();
	}
	
	public void step() {
		initShots(addList);
		
		for (ShotModel s : this) {
			if (!s.killed) s.step(this);
			if (s.killed)  removeShot(s);
		}

		garbageCollect(removeList);
		
		//long time = System.nanoTime();
		colGrid.collide(shots);
		//System.out.printf("S<->S :: %.2f\n", (float)((System.nanoTime() - time) / 1000000.0));
		
		garbageCollect(removeList);
	}
	
	public void collideRect(SpriteShotColHandler handler, Sprite s, ColRectMode m, Rectangle r) {
		colGrid.collideRect(handler, s, m, r);
	}
	
	public Iterator<ShotModel> iterator() {
		return shots.iterator();
	}
	
	protected void updateShotPosition(ShotModel s) {
		for (int n = 0; n < s.colNodesL; n++) {
			colGrid.updateNodeCell(s.colNodes[n]);
		}
	}
	
	//Getters
	public int getGridSize() { return 64; }
	public int toGridCoord(float x) { return toGridCoord(Math.round(x)); }
	public int toGridCoord(int x) { return x>>6; }
	public int fromGridCoord(int x) { return x<<6; }
	public Collection<ShotModel> getShots() { return shots; }
	
	//Setters
		
}
